/*
	Class: ContainerImage

		The ContainerImage class is used to implement the <image /> tag. It may
		be used to display images, SWFs or DisplayObject symbols exported in the
		library (either internal or external).
		
		To load an image or SWF, specify the src attribute on the image tag. An
		Asset object will be created for the external asset and its 
		DisplayObject add to this container. On a successful load, if the 
		container has the width or height style set to auto (which is the 
		default value for the image tag), then these styles will be set based on 
		the dimensions of the loaded asset. If the width or height style is set, 
		then the resize-scale and resize-scale-origin styles are processed based 
		on the asset dimensions and the specified width and/or height.
		
		To load a symbol, specify the symbol attribute on the image tag. The
		ExternalAssetManager will make an attempt to find the symbol in the
		current application domain. If it cannot, it will look through any 
		loaded external asset libraries. If it still cannot find the symbol, 
		then it will call onLoadExternalAsset when and if any external asset
		library is loaded. Note that you can force a symbol to be taken from a
		particular external asset library via the externalAssetSrc attribute of 
		the image tag.
		
		JavaScript-style animation may be achieved by change the src and symbol
		attributes of the image. For example:
		
		<image src="img.jpg" onMouseOver="setAttribute('src','over.jpg');" onMouseOut="setAttribute('src','img.jpg');" />
		
		To achieve this, ContainerImage maintains an array of assets. There is
		no limit to the length of this array so care should be taken. To pre-
		load an asset into this array, use the preloadImage method. For example:
		
		<image src="img.jpg" onMouseOver="setAttribute('src','over.jpg');" onMouseOut="setAttribute('src','img.jpg');" onRender="preloadImage('over.jpg');" />
		
		Note that we do not actually switch the image until the new image is
		ready to be displayed. This is to avoid the situation where if we were
		to swap in an image that wasn't ready yet, a mouse out event would be 
		created and in the example above we'd go into an infinite loop.
*/
package com.frontalcode 
{
	import flash.events.*;
	import flash.display.*;
	import flash.utils.*;
	import flash.geom.*;
	
	/**
	 * The ContainerImage class handles the <img /> tag.
	 */
    public class ContainerImage extends Container
    {
		/**
		 * @private
		 */
		internal var assets : Array = [ ];								// An Array of Assets associated with this image tag.
		
		private var _image : DisplayObject;						// The current DisplayObject for the image tag.
		private var _imageIsSymbol : Boolean;					// Is the current image a symbol (as opposed to an external JPG, GIF, PNG or SWF)?
		private var _imageSrc : String;							// The URL or class name of the current image.
		
		private var _loadingImage : DisplayObject;				// The currently loading DisplayObject for the image tag.
		private var _loadingImageIsSymbol : Boolean;			// Is the loading image a symbol (as opposed to an external JPG, GIF, PNG or SWF)?
		private var _loadingImageSrc : String;					// The URL or class name of the loading image.
		private var loadingImageAtReset : Boolean = false;		// Do we need to do a reset on the image on load?
		
		/**
		 * @private
		 */
		internal var imageDimensions : Dictionary = new Dictionary ( );	// The original dimensions of loaded image and SWF files.
		
		/**
		 * @private
		 */
		internal var imageOffset : Point = new Point ( );				// The offset of the showall or showmost scaled image.
		
		/**
		 * @private
		 */
		internal var needsImageResize : Boolean = false;					// Do we need to run imageResize ( ) during the next render?
		
		/**
		 * @private
		 */
		internal var resizeScaleAtResize : String;
		
		/**
		 * @private
		 */
		internal var resizeScaleOriginAtResize : String;
		
		/**
		 * @private
		 */
		public var contentMask : DisplayObject;

		/**
		 * Creates a new ContainerImage instance.
		 * 
		 * @param document	The document this element belongs to.
		 * @param parent	The element's parent in the document tree.
		 * @param node		The XML node this element is associated with.
		 * @param options	Options affecting the behavior of this instance.
		 * 					(This object does not have built-in support for any
		 * 					options.)
		 */
		public function ContainerImage ( document : Document, parent : DocumentElement, node : XML, options : Object = null )
		{
			super ( document, parent, node, options );
		}
		
		/**
		 * The DisplayObject of the current image.
		 */
		public function get image ( ) : DisplayObject { return _image; }
		
		/**
		 * Is the current image a symbol?
		 */
		public function get imageIsSymbol ( ) : Boolean { return _imageIsSymbol; }
		
		/**
		 * The src attribute associated with this image.
		 */
		public function get imageSrc ( ) : String { return _imageSrc; }
		
		/**
		 * The DisplayObject of the currently loading image.
		 */
		public function get loadingImage ( ) : DisplayObject { return _loadingImage; }
		
		/**
		 * Is the currently loading image a symbol?
		 */
		public function get loadingImageIsSymbol ( ) : Boolean { return _loadingImageIsSymbol; }
		
		/**
		 * The src attribute associated with the currently loading image.
		 */
		public function get loadingImageSrc ( ) : String { return _loadingImageSrc; }
		
		override public function destroy ( ) : void
		{
			// Unload our assets.
			//
			for ( var i : uint = 0; i < assets.length; i++ ) AssetManager.getInstance ( ).unloadObject ( assets [ i ] );
			assets = [ ];
			
			super.destroy ( );
		}
		
		/*
			Function: firstDocumentRenderHandler
				
				We want to prepare our assets after we've had a chance to apply 
				styles like base-url. We can't just do this in render because we
				may be a child of an element with "display: none;" set and so
				render may not come until we actually want to see the image.
		*/
		/**
		 * @private
		 */
		override public function onFirstDocumentPreRender ( ) : void
		{
			super.onFirstDocumentPreRender ( );
			if ( getStyle ( "preload-assets" ) && attributeExists ( "src" ) ) customRender ( );
		}
		
		/**
		 * Preload the image associated with this value of the src attribute.
		 */
		public function preloadImage ( src : String ) : Asset
		{
			if ( src == null || Util.isEmpty.test ( src ) ) return null;
			
			var asset : Asset = findAsset ( src );
			if ( asset == null )
			{
				// Smoothing requires access to the bitmap data and so
				// we want to check the policy file if this style is 
				// turned on.
				//
				var checkPolicyFile : Boolean = ( getStyle ( "allow-smoothing" ) || getStyle ( "check-policy-file" ) ) && getStyle ( "check-policy-file" ) !== false;
				asset = new Asset ( document, src, getStyle ( "base-url" ), checkPolicyFile, getStyle ( "policy-file-url" ), getStyle ( "load-in-current-app-and-sec-domains" ) );
				addListener ( asset.loader.contentLoaderInfo, ProgressEvent.PROGRESS, assetProgressHandler );
				AssetManager.getInstance ( ).preloadObject ( asset );
				assets.push ( asset );
			}
			return asset;
		}
		
		/**
		 * @private
		 */
		override public function applyStyles ( ) : void
		{
			if ( getStyle ( "wants-reset" ) !== false ) setStyle ( "wants-reset", true );
			
			super.applyStyles ( );
			
			try
			{
				if ( image != null && image is Loader && ( image as Loader ).content != null && ( image as Loader ).contentLoaderInfo.contentType != "application/x-shockwave-flash" ) ( ( image as Loader ).content as Bitmap ).smoothing = getStyle ( "allow-smoothing" );
			}
			catch ( error : SecurityError )
			{
				var asset : Asset = findAsset ( imageSrc );
				if ( asset != null && ! asset.policyFileRequested ) asset.loadPolicyFile ( );
			}
			
			goToLabel ( getStyle ( "go-to-label" ), getStyle ( "go-to-and-play" ) );
		}
		
		/**
		 * @private
		 */
		override public function applyInteractions ( ) : void
		{
			super.applyInteractions ( );
			applyInteraction ( FrontalEvent.LOADED );
			applyInteraction ( FrontalEvent.FAILED );
		}
		
		/**
		 * @private
		 */
		override public function reset ( ) : void
		{
			super.reset ( );
			
			goToLabel ( getStyle ( "reset-go-to-label" ), getStyle ( "reset-go-to-and-play" ) );
			
			// Do we need to try again on load?
			//
			loadingImageAtReset = loadingImage != null;
		}
		
		/**
		 * Tell the image (as a MovieClip) to go to the named frame and 
		 * optionally play.
		 */
		public function goToLabel ( name : String, play : Boolean ) : void
		{
			if ( name != null && image != null )
			{
 				var target : DisplayObject = getPseudoClassState ( "isSWF" ) ? ( image as Loader ).content : image;
				if ( target is MovieClip )
				{
					var frame : Number = Number ( name ); 
					if ( isNaN ( frame ) )
					{
						for each ( var label : FrameLabel in ( target as MovieClip ).currentLabels )
						{
							if ( label.name == name )
							{
								frame = label.frame;
								break;
							}
						}
					}
					
					if ( ! isNaN ( frame ) ) ( target as MovieClip ) [ play ? "gotoAndPlay" : "gotoAndStop" ] ( frame );
				}
			}
		}
		
		/**
		 * @private
		 */
		override public function initializeRender ( ) : void
		{
			super.initializeRender ( );
			addListener ( this, FrontalEvent.RESIZE, resizeImageHandler );
		}
		
		/**
		 * @private
		 */
		override public function customRender ( ) : void
		{
			super.customRender ( );
			
			if ( 
					(	// Is the src or symbol attribute out of synch with our image?
						image == null ||
						(   imageIsSymbol && imageSrc != getAttribute ( "symbol" ) ) ||
						( ! imageIsSymbol && imageSrc != getAttribute ( "src" ) )
					) 
					&&
					(	// And is it different from our loading image?
						loadingImage == null ||
						(   loadingImageIsSymbol && loadingImageSrc != getAttribute ( "symbol" ) ) ||
						( ! loadingImageIsSymbol && loadingImageSrc != getAttribute ( "src" ) )
					)
				)
			{
				// Handle the change in the image source. Remove any listeners 
				// we might have.
				//
				if ( loadingImageSrc != null )
				{
					var asset : Asset = findAsset ( loadingImageSrc );
					if ( asset != null )
					{
						removeListener ( asset, FrontalEvent.LOADED, onLoad );
						removeListener ( asset, FrontalEvent.FAILED, onLoadFailed );
					}
					if ( loadingImageIsSymbol ) document.externalAssetManager.ignoreDefinition ( loadingImageSrc, onLoadExternalAsset, getAttribute ( "externalAssetSrc" ) );
				}
				
				if ( ! Util.isEmpty.test ( getAttribute ( "src" ) ) )
				{
					_loadingImageIsSymbol = false;
					_loadingImageSrc = getAttribute ( "src" );
					asset = preloadImage ( _loadingImageSrc );
					addListener ( asset, FrontalEvent.LOADED, onLoad );
					addListener ( asset, FrontalEvent.FAILED, onLoadFailed );
					_loadingImage = asset.loader;
					if ( asset.state == Asset.LOADED ) swapImage ( );
				}
				else if ( ! Util.isEmpty.test ( getAttribute ( "symbol" ) ) )
				{
					_loadingImageIsSymbol = true;
					_loadingImageSrc = getAttribute ( "symbol" );
					
					var classRef : Class = document.externalAssetManager.getDefinition ( getAttribute ( "symbol" ), onLoadExternalAsset, getAttribute ( "externalAssetSrc" ) );
					if ( classRef != null )
					{
						_loadingImage = new classRef ( ) as DisplayObject;
						swapImage ( );
					}
				}
			}
			
			if ( needsImageResize || getStyle ( "resize-scale" ) != resizeScaleAtResize || getStyle ( "resize-scale-origin" ) != resizeScaleOriginAtResize ) resizeImage ( );
		}
		
		/**
		 * @private
		 */
		override public function renderMask ( ) : void
		{
			super.renderMask ( );
			
			if ( getStyle ( "overflow" ) != "hidden" || image == null ) 
			{
				if ( contentMask != null )
				{
					image.mask = null;
					if ( contentMask.parent != null ) contentMask.parent.removeChild ( contentMask );
					contentMask = null;
				}
				return;
			}
			
			if ( image == null ) return;
			
			if ( contentMask != null && contentMask.parent != null && contentMask.width == contentWidth && contentMask.height == contentHeight ) return;
			
			var maskShape : Shape = contentMask == null ? new Shape ( ) : contentMask as Shape;
			maskShape.graphics.clear ( );
			maskShape.graphics.beginFill ( 0 );
			maskShape.graphics.drawRect ( 0, 0, contentWidth, contentHeight );
			maskShape.graphics.endFill ( );
			contentMask = maskShape;

			movie.addChild ( contentMask );
			image.mask = contentMask;
		}
		
		/**
		 * @private
		 */
		internal function resizeImageHandler ( event : FrontalEvent ) : void	{ needsImageResize = true; }
		
		/**
		 * @private
		 */
		internal function resizeImage ( ) : void
		{
			resizeScaleAtResize			= getStyle ( "resize-scale" );
			resizeScaleOriginAtResize	= getStyle ( "resize-scale-origin" );
		
			needsImageResize = false;
			if ( image == null ) return;
			
			var scaleX : Number = 1;
			var scaleY : Number = 1;
			var x : Number = 0;
			var y : Number = 0;
			var dimensions : Object = imageDimensions [ image ];
			
			if ( imageIsSymbol && ! dimensions.setManually )
			{
				// MovieClip dimensions tend to change as they are usually 
				// animated so in this case we work out the dimensions from the
				// current width, height and scale.
				//
				dimensions.rect.width = image.width / image.scaleX;
				dimensions.rect.height = image.height / image.scaleY;
			}
			
			if ( getStyle ( "resize-scale" ) != "none" )
			{
				var widthSpecified  : Boolean = ! isNaN ( width  ) && nonAutoWidthSpecified;
				var heightSpecified : Boolean = ! isNaN ( height ) && nonAutoHeightSpecified;
			
				if ( widthSpecified && ! heightSpecified )
				{
					// Handle the situation where we have a width but no height.
					//
					scaleX = scaleY = contentWidth / dimensions.rect.width;
				}
				else if ( heightSpecified && ! widthSpecified )
				{
					// Handle the situation where we have a height but no width.
					//
					scaleX = scaleY = contentHeight / dimensions.rect.height;
				}
				else if ( heightSpecified && widthSpecified )
				{
					scaleX = contentWidth / dimensions.rect.width;
					scaleY = contentHeight / dimensions.rect.height;
					
					if ( getStyle ( "resize-scale" ) == "showmost" )
					{
						scaleX = scaleY = Math.max ( scaleX, scaleY );
					}
					else if ( getStyle ( "resize-scale" ) == "showall" )
					{
						scaleX = scaleY = Math.min ( scaleX, scaleY );
					}
				}
			}
						
			// resize-scale-origin is a combination of top, left, 
			// bottom, right, center (horizontal) and middle (vertical).
			//
			var origin : String = getStyle ( "resize-scale-origin" );
			
			if ( origin != null )
			{
				origin = origin.toLowerCase ( );

				if ( origin.indexOf ( "center" ) >= 0 )
				{
					x = ( contentWidth - dimensions.rect.width * scaleX ) / 2;
				}
				else if ( origin.indexOf ( "right" ) >= 0 )
				{
					x = contentWidth - dimensions.rect.width * scaleX;
				}
	
				if ( origin.indexOf ( "middle" ) >= 0 )
				{
					y = ( contentHeight - dimensions.rect.height * scaleY ) / 2;
				}
				else if ( origin.indexOf ( "bottom" ) >= 0 )
				{
					y = contentHeight - dimensions.rect.height * scaleY;
				}
			}
			
			image.scaleX = scaleX;
			image.scaleY = scaleY;
			imageOffset.x = x;
			imageOffset.y = y;

			if ( debugOptions [ "render" ] ) trace ( node.@id, "resizeImage", "width:", image.width, "height:", image.height, "scaleX:", image.scaleX, "scaleY:", image.scaleY, "offsetX:", x, "offsetY:", y );
			
			// Apply any new scroll maximums.
			//
			scrollTop = -y;
			scrollLeft = -x;
		}
		
		/**
		 * @private
		 */
		override public function set scrollTop ( value : Number ) : void
		{
			super.scrollTop = value;
			if ( image != null )
			{
				if ( scrollTopMax > 0 )
				{
					image.y = -scrollTop;
				}
				else
				{
					// Otherwise position the image according to the 
					// resize-scale-origin style.
					//
					image.y = imageOffset.y;
				}
			}
		}
		
		/**
		 * @private
		 */
		override public function set scrollLeft ( value : Number ) : void
		{
			super.scrollLeft = value;
			if ( image != null ) 
			{
				if ( scrollLeftMax > 0 )
				{
					image.x = -scrollLeft;
				}
				else
				{
					// Otherwise position the image according to the 
					// resize-scale-origin style.
					//
					image.x = imageOffset.x;
				}
			}
		}
		
		/*
			Function: swapImage
			
				The loadingImage is ready now for display. We put it in the 
				display list, remove the current image, transfer the attributes
				and clear the loadingImage members.
		*/
		/**
		 * @private
		 */
		internal function swapImage ( ) : void
		{
			if ( loadingImage != null ) 
			{
				// If we haven't seen this image before then capture its 
				// original dimensions.
				//
				var imgIsSWF : Boolean = false;
				
				try
				{
					imgIsSWF = ( loadingImage as Loader ).contentLoaderInfo.contentType == "application/x-shockwave-flash";
				}
				catch ( e : Error )
				{
				}
				
				if ( imageDimensions [ loadingImage ] == null ) 
				{
					var dimensions : * = runInteractions ( "getImageDimensions", { image: loadingImage, src: loadingImageSrc, isSymbol: loadingImageIsSymbol } );
					if ( dimensions != null && dimensions.hasOwnProperty ( "width" ) && dimensions.hasOwnProperty ( "height" ) )
					{
						imageDimensions [ loadingImage ] = { setManually: true, rect: new Rectangle ( 0, 0, dimensions.width, dimensions.height ) };
					}
					else
					{
						if ( imgIsSWF ) 
						{
							imageDimensions [ loadingImage ] = { setManually: false, rect: new Rectangle ( 0, 0, ( loadingImage as Loader ).contentLoaderInfo.width, ( loadingImage as Loader ).contentLoaderInfo.height ) };
						}
						else
						{
							imageDimensions [ loadingImage ] = { setManually: false, rect: new Rectangle ( 0, 0, loadingImage.width, loadingImage.height ) };
						}
					}
				}
				movie.addChildAt ( loadingImage, 0 );
				if ( image != null ) image.parent.removeChild ( image );
				_image = loadingImage;
				_imageSrc = loadingImageSrc;
				_imageIsSymbol = loadingImageIsSymbol;
				_loadingImage = null;
				_loadingImageSrc = null;
				setPseudoClassState ( "isImage", ! imageIsSymbol && ! imgIsSWF );
				setPseudoClassState ( "isSWF", imgIsSWF );
				setPseudoClassState ( "isSymbol", imageIsSymbol );
				needsLayout = true;
				
				if ( loadingImageAtReset ) goToLabel ( getStyle ( "reset-go-to-label" ), getStyle ( "reset-go-to-and-play" ) );
				
				runInteractions ( "onImageReady" );
			}
		}
		
		/**
		 * @private
		 */
		internal function findAsset ( src : String ) : Asset
		{
			for ( var i : uint = 0; i < assets.length; i++ )
			{
				if ( assets [ i ].rawURL == src ) return assets [ i ];
			}
			
			return null;
		}
		
		/**
		 * @private
		 */
		override public function get intrinsicWidth ( ) : Number 
		{
			var value : Number;
			if ( image != null ) value = image.width;
			return value;
		}
		
		/**
		 * @private
		 */
		override public function get intrinsicHeight ( ) : Number 
		{ 
			var value : Number;
			if ( image != null ) value = image.height;
			return value;
		}
		
		/**
		 * @private
		 */
		override public function prepareAssets ( ) : void
		{
			super.prepareAssets ( );
			
			if ( ! Util.isEmpty.test ( getAttribute ( "src" ) ) ) preloadImage ( getAttribute ( "src" ) );		
			
			for ( var i : int = assets.length - 1; i >= 0; i-- )
			{
				if ( assets [ i ].loader !== loadingImage ) AssetManager.getInstance ( ).demandObject ( assets [ i ] );
			}
			
			// Demand the current asset last.
			//
			if ( loadingImage != null && ! loadingImageIsSymbol )
			{
				var asset : Asset = findAsset ( loadingImageSrc );
				if ( asset != null ) AssetManager.getInstance ( ).demandObject ( asset );
			}
		}
		
		/*
			Function: onLoad
			
				This function will be called if the current image has been
				loaded. In this case, current image refers to the image
				specified via the current "src" attribute. This is _not_ the
				image referred to by the image member. That is, in the scenario
				that src is initially "image1.jpg" then this method is called
				when that image is loaded. In that case, the image member is
				null at this point. Then if src is changed to "image2.jpg" then
				the load process for that image is begun but the image member is
				not initially changed from pointing at the result of loading
				"image1.jpg." When the new image loads, then this function will
				be called. So to be clear, images begin loaded either via the
				method preloadImage or via switching the src attribute prior to
				an image loading, will not result in this method being called if
				they do not refer to the current image as defined above.
		*/
		/**
		 * Called when the image is loaded.
		 */
		public function onLoad ( event : FrontalEvent ) : void
		{
			swapImage ( );
			needsImageResize = true;
			dispatchEvent ( event );
		}
		
		/**
		 * Called when the image load fails.
		 */
		public function onLoadFailed ( event : FrontalEvent ) : void { dispatchEvent ( event ); }
		
		/*
			Function: onLoadExternalAsset
			
				This method is called when an external asset has been loaded
				that resolves our current image's class. It is only called if it
				pertains to our current image (as defined in the discussion of
				the onLoad method).
		*/
		/**
		 * @private
		 */
		public function onLoadExternalAsset ( name : String, externalAssetSrc : String, classRef : Class ) : void
		{
			_loadingImage = new classRef ( ) as DisplayObject;
			swapImage ( );
			runInteractions ( "onLoad" );
		}
		
		/*
			Function: calculateLoadProgress
			
				Add our images load progress to the total progress. Use the
				style "progress-includes-all-assets" to determine if we only 
				report on the progress of our current image (as specified by the
				src or symbol attribute) or if we report on all of our assets
				including those being pre-loaded.
				
			Parameters:
			
				progress	- The progress statistics calculated so far.
				
			Notes:
				
				We currently do not track the loading of symbols in external
				resources SWFs very well; we just report if the symbol is loaded
				or not. There are few technical issues to figure out including
				overcoming the fact that it's not necessary to know which 
				external resource library includes our particular symbol of
				interest.
		*/
		/**
		 * @private
		 */
		override public function calculateLoadProgress ( progress : Object ) : void 
		{ 
			// Each asset to be loaded weighs equally in the progress 
			// fraction. It would be preferable to give them weight 
			// according to their size but at any point we may not know the
			// size of one or more of the assets. So to at least ensure that
			// the progress fraction always moves forward, we do things this
			// way.
			//
			var subEntries : Array = [ ];
			for ( var i : uint = 0; i < assets.length; i++ )
			{
				if ( getStyle ( "progress-includes-all-assets" ) || assets [ i ].loader === loadingImage || assets [ i ].loader === image )
				{
					// XXX Also handle strangeness on IE where bytesLoaded 
					// is a non-zero value but bytesTotal is zero.
					//
					subEntries.push ( 
						{ 
							bytesLoaded: assets [ i ].bytesLoaded, 
							bytesTotal: assets [ i ].bytesTotal == 0 && assets [ i ].bytesLoaded > 0 ? assets [ i ].bytesLoaded : assets [ i ].bytesTotal 
						} );
				}
			}
			
			if ( loadingImage != null && loadingImageIsSymbol )
			{
				// Add some token amount to the total number of bytes to 
				// indicate that we're not yet loaded.
				//
				subEntries.push ( { bytesLoaded: 0, bytesTotal: 1 } );
			}
			
			if ( image != null && imageIsSymbol )
			{
				// If we are a symbol and we're loaded add and entry for that.
				//
				subEntries.push ( { bytesLoaded: 1, bytesTotal: 1 } );
			}
			
			var entry : Object = {
					docElem: this,
					bytesLoaded: 0,
					bytesTotal: 0,
					fraction: 0		// This is not necessarily bytesLoaded / bytesTotal. See discussion above.
				};
			
			for ( i = 0; i < subEntries.length; i++ )
			{
				entry.bytesLoaded += subEntries [ i ].bytesLoaded;
				entry.bytesTotal += subEntries [ i ].bytesTotal;
				if ( subEntries [ i ].bytesTotal > 0 ) entry.fraction += ( subEntries [ i ].bytesLoaded / subEntries [ i ].bytesTotal ) * ( 1 / subEntries.length ); 
			}
			
			// If this looks like an empty img tag (no src or symbol attribute)
			// then we mark it as loaded.
			//
			if ( subEntries.length == 0 && Util.isEmpty.test ( getAttribute ( "src" ) ) && Util.isEmpty.test ( getAttribute ( "symbol" ) ) ) entry.fraction = 1;
			
			progress.entries.push ( entry );
			
			super.calculateLoadProgress ( progress );
		}
		
		/**
		 * @private
		 */
		internal function assetProgressHandler ( event : ProgressEvent ) : void
		{
			dispatchEvent ( new FrontalEvent ( FrontalEvent.PROGRESS ) );
		}
	}
}
